'''
1、网络的概念：将具有独立功能的多台计算机通过通信线路和通信设备连接起来，在网络管理软件和网络通信协议下，实现资源共享和信息传递的虚拟平台
            简而言之，网络是实现资源共享和信息传递的虚拟平台，可以编写基于网络通信的程序（后续的socket编程、web开发等）
2、IP地址：分配给网络设备上网使用的数字标签，能够标识网络中唯一的一台设备（如现实中的手机号）
3、命令：
     ifconfig：查看网卡信息       （虚拟机终端输入查看）
     ping：    检查网络是否正常
4、端口和端口号：
      端口：传输数据的通道，是数据传输的必经之路
      端口号：用来管理区分不同端口的号码
        分类-知名端口号:0-1023（如119火警号，已被规定使用）
            动态端口号：1024-65535（程序员开发应用程序使用的）
      网络通信流程：通过ip地址找到对应的设备，通过端口号找到对应的端口，通过端口把数据给应用程序
5、socket：套接字，是程序之间进行网络通讯的工具（如使用手机才能通讯）
           只要跟网络相关的应用程序和软件，都使用了socket
6、TCP：数据传输之前需要选择网络传输方式（传输协议），保证程序之间按照规定的传输规则进行数据的通信（如乡间小路、高速公路）
       transmission control protocol，传输控制协议，一种面向连接的、可靠的、基于字节流的传输层通信协议
       特点：
         面向连接：必须先连接，双方必须分配必要资源来记录连接的状态和信息，数据传输完成后，必须断开连接，释放系统资源
         可靠传递：采用发送应答机制、超时重传、错误校验、流量控制和阻塞管理
       通信步骤：
          创建连接
          传输数据
          关闭连接
7、python3编码转换
    网络传输是以二进制数据进行传输
    str.encode(encoding='utf-8')    编码（转化成二进制，字符串->字节）
    bytes.decode(encoding='utf-8')  解码（字节->字符串）
8、TCP客户端程序开发流程
    补充：客户端程序（运行在用户设备上的程序）
         服务端程序（运行在服务器设备上的程序，专门为客户端提供数据服务）
         客户端+服务端，一个网络应用才能真正使用
    流程：① 创建客户端套接字对象（买手机）
         ② 和服务端套接字建立连接（打电话）  -connect(IP地址，端口号)
         ③ 发送数据（说话）               -send
         ④ 接收数据（接听）               -recv
         ⑤ 关闭客户端套接字（挂电话）       -close
    实现：
9、TCP服务端程序开发流程
    流程：① 创建服务端套接字对象
         ② 绑定IP地址和端口号        -bind
         ③ 设置监听                -listen
         ④ 等待接受客户端的连接请求   -accept
         ⑤ 接收数据                -recv
         ⑥ 发送数据                -send
         ⑦ 关闭套接字              -close
10、send和recv原理：
    客户端程序（客户端数据-socket-发送缓冲区-客户端网卡-服务端网卡-接收缓冲区-socket-接收到客户端数据）服务端程序
'''
# 客户端
import socket
if __name__ == '__main__':
    tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET(IPV4)、SOCK_STREAM(TCP通讯方式)
    tcp_client_socket.connect(("192.168.88.131", 8080))  # 参数是一个元组，192.168.88.131(终端输入ifconfig，查看ens33的inet），8080随意设置端口号
    tcp_client_socket.send("hello world".encode(encoding='utf-8'))
    recv_data = tcp_client_socket.recv(1024)  # 随意设置大小
    print(recv_data.decode(encoding='utf-8'))   # 可不写encoding，默认为'utf-8'
    tcp_client_socket.close()

# 服务端
import socket
import threading

def handle(conn_socket):
    recv_data = conn_socket.recv(1024)
    print(f"接收到的数据：{recv_data.decode()}")
    conn_socket.send("客户端你的数据我收到了".encode())
    conn_socket.close()

if __name__ == '__main__':
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)  # 设置端口复用
    tcp_server_socket.bind(("", 8888))  # ""（默认为本机ip地址）
    tcp_server_socket.listen(128)  # 128代表服务器等待排队连接的最大数量
    while True:
        conn_socket, ip_port = tcp_server_socket.accept()  # accept阻塞等待，返回一个客户端通信的socket，客户端地址
        print(f"客户端地址：{ip_port}")
        sub_thread = threading.Thread(target=handle, args=(conn_socket,))   # 创建多线程，实现多任务TCP服务端程序开发
        sub_thread.start()
    tcp_server_socket.close()


